package com.example.javapoet.demo.scenarios;

import com.squareup.javapoet.*;
import org.springframework.web.bind.annotation.*;
import javax.lang.model.element.Modifier;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * JavaPoet场景示例 - 生成REST API代码
 */
public class RestApiGeneration {

    public static void main(String[] args) {
        // 生成用户控制器类
        generateUserController();
        
        // 生成用户服务类
        generateUserService();
        
        // 生成用户实体类
        generateUserEntity();
    }

    /**
     * 生成用户控制器类
     */
    public static void generateUserController() {
        // 创建方法
        MethodSpec getAllUsersMethod = MethodSpec.methodBuilder("getAllUsers")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(AnnotationSpec.builder(GetMapping.class)
                        .addMember("value", "$S", "/users")
                        .build())
                .returns(ParameterizedTypeName.get(
                        ClassName.get(List.class),
                        ClassName.get("com.example.api.model", "User")))
                .addStatement("return userService.getAllUsers()")
                .build();
        
        MethodSpec getUserByIdMethod = MethodSpec.methodBuilder("getUserById")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(AnnotationSpec.builder(GetMapping.class)
                        .addMember("value", "$S", "/users/{id}")
                        .build())
                .returns(ClassName.get("com.example.api.model", "User"))
                .addParameter(ParameterSpec.builder(long.class, "id")
                        .addAnnotation(AnnotationSpec.builder(PathVariable.class)
                                .addMember("value", "$S", "id")
                                .build())
                        .build())
                .addStatement("return userService.getUserById(id)")
                .build();
        
        MethodSpec createUserMethod = MethodSpec.methodBuilder("createUser")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(AnnotationSpec.builder(PostMapping.class)
                        .addMember("value", "$S", "/users")
                        .build())
                .returns(ClassName.get("com.example.api.model", "User"))
                .addParameter(ParameterSpec.builder(ClassName.get("com.example.api.model", "User"), "user")
                        .addAnnotation(AnnotationSpec.builder(RequestBody.class)
                                .build())
                        .build())
                .addStatement("return userService.createUser(user)")
                .build();
        
        MethodSpec updateUserMethod = MethodSpec.methodBuilder("updateUser")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(AnnotationSpec.builder(PutMapping.class)
                        .addMember("value", "$S", "/users/{id}")
                        .build())
                .returns(ClassName.get("com.example.api.model", "User"))
                .addParameter(ParameterSpec.builder(long.class, "id")
                        .addAnnotation(AnnotationSpec.builder(PathVariable.class)
                                .addMember("value", "$S", "id")
                                .build())
                        .build())
                .addParameter(ParameterSpec.builder(ClassName.get("com.example.api.model", "User"), "user")
                        .addAnnotation(AnnotationSpec.builder(RequestBody.class)
                                .build())
                        .build())
                .addStatement("return userService.updateUser(id, user)")
                .build();
        
        MethodSpec deleteUserMethod = MethodSpec.methodBuilder("deleteUser")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(AnnotationSpec.builder(DeleteMapping.class)
                        .addMember("value", "$S", "/users/{id}")
                        .build())
                .returns(void.class)
                .addParameter(ParameterSpec.builder(long.class, "id")
                        .addAnnotation(AnnotationSpec.builder(PathVariable.class)
                                .addMember("value", "$S", "id")
                                .build())
                        .build())
                .addStatement("userService.deleteUser(id)")
                .build();
        
        // 创建字段
        FieldSpec userServiceField = FieldSpec.builder(
                ClassName.get("com.example.api.service", "UserService"), 
                "userService")
                .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
                .build();
        
        // 创建构造函数
        MethodSpec constructor = MethodSpec.constructorBuilder()
                .addModifiers(Modifier.PUBLIC)
                .addParameter(ClassName.get("com.example.api.service", "UserService"), "userService")
                .addStatement("this.userService = userService")
                .build();
        
        // 创建类
        TypeSpec userControllerClass = TypeSpec.classBuilder("UserController")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(AnnotationSpec.builder(RestController.class)
                        .addMember("value", "$S", "/api")
                        .build())
                .addAnnotation(AnnotationSpec.builder(RequestMapping.class)
                        .addMember("value", "$S", "/api/v1")
                        .build())
                .addField(userServiceField)
                .addMethod(constructor)
                .addMethod(getAllUsersMethod)
                .addMethod(getUserByIdMethod)
                .addMethod(createUserMethod)
                .addMethod(updateUserMethod)
                .addMethod(deleteUserMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.api.controller", userControllerClass)
                .build();

        try {
            // 输出到控制台
            System.out.println("生成UserController类:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成UserController.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成用户服务类
     */
    public static void generateUserService() {
        // 创建接口
        TypeSpec userServiceInterface = TypeSpec.interfaceBuilder("UserService")
                .addModifiers(Modifier.PUBLIC)
                .addMethod(MethodSpec.methodBuilder("getAllUsers")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(ParameterizedTypeName.get(
                                ClassName.get(List.class),
                                ClassName.get("com.example.api.model", "User")))
                        .build())
                .addMethod(MethodSpec.methodBuilder("getUserById")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(ClassName.get("com.example.api.model", "User"))
                        .addParameter(long.class, "id")
                        .build())
                .addMethod(MethodSpec.methodBuilder("createUser")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(ClassName.get("com.example.api.model", "User"))
                        .addParameter(ClassName.get("com.example.api.model", "User"), "user")
                        .build())
                .addMethod(MethodSpec.methodBuilder("updateUser")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(ClassName.get("com.example.api.model", "User"))
                        .addParameter(long.class, "id")
                        .addParameter(ClassName.get("com.example.api.model", "User"), "user")
                        .build())
                .addMethod(MethodSpec.methodBuilder("deleteUser")
                        .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
                        .returns(void.class)
                        .addParameter(long.class, "id")
                        .build())
                .build();
        
        // 创建实现类
        TypeSpec userServiceImplClass = TypeSpec.classBuilder("UserServiceImpl")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Service.class)
                .addSuperinterface(ClassName.get("com.example.api.service", "UserService"))
                .addField(FieldSpec.builder(
                        ParameterizedTypeName.get(
                                ClassName.get(Map.class),
                                ClassName.get(Long.class),
                                ClassName.get("com.example.api.model", "User")),
                        "users")
                        .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
                        .initializer("new $T<>()", HashMap.class)
                        .build())
                .addMethod(MethodSpec.constructorBuilder()
                        .addModifiers(Modifier.PUBLIC)
                        .addStatement("// 初始化一些测试数据")
                        .addStatement("users.put(1L, new $T(1L, $S, $S))", 
                                ClassName.get("com.example.api.model", "User"), "Alice", "alice@example.com")
                        .addStatement("users.put(2L, new $T(2L, $S, $S))", 
                                ClassName.get("com.example.api.model", "User"), "Bob", "bob@example.com")
                        .build())
                .addMethod(MethodSpec.methodBuilder("getAllUsers")
                        .addAnnotation(Override.class)
                        .addModifiers(Modifier.PUBLIC)
                        .returns(ParameterizedTypeName.get(
                                ClassName.get(List.class),
                                ClassName.get("com.example.api.model", "User")))
                        .addStatement("return new $T<>(users.values())", ArrayList.class)
                        .build())
                .addMethod(MethodSpec.methodBuilder("getUserById")
                        .addAnnotation(Override.class)
                        .addModifiers(Modifier.PUBLIC)
                        .returns(ClassName.get("com.example.api.model", "User"))
                        .addParameter(long.class, "id")
                        .addStatement("return users.get(id)")
                        .build())
                .addMethod(MethodSpec.methodBuilder("createUser")
                        .addAnnotation(Override.class)
                        .addModifiers(Modifier.PUBLIC)
                        .returns(ClassName.get("com.example.api.model", "User"))
                        .addParameter(ClassName.get("com.example.api.model", "User"), "user")
                        .addStatement("long id = users.keySet().stream().max(Long::compare).orElse(0L) + 1")
                        .addStatement("user.setId(id)")
                        .addStatement("users.put(id, user)")
                        .addStatement("return user")
                        .build())
                .addMethod(MethodSpec.methodBuilder("updateUser")
                        .addAnnotation(Override.class)
                        .addModifiers(Modifier.PUBLIC)
                        .returns(ClassName.get("com.example.api.model", "User"))
                        .addParameter(long.class, "id")
                        .addParameter(ClassName.get("com.example.api.model", "User"), "user")
                        .addStatement("user.setId(id)")
                        .addStatement("users.put(id, user)")
                        .addStatement("return user")
                        .build())
                .addMethod(MethodSpec.methodBuilder("deleteUser")
                        .addAnnotation(Override.class)
                        .addModifiers(Modifier.PUBLIC)
                        .returns(void.class)
                        .addParameter(long.class, "id")
                        .addStatement("users.remove(id)")
                        .build())
                .build();
        
        // 创建Java文件
        JavaFile interfaceFile = JavaFile.builder("com.example.api.service", userServiceInterface)
                .build();
        
        JavaFile implFile = JavaFile.builder("com.example.api.service", userServiceImplClass)
                .build();

        try {
            // 输出到控制台
            System.out.println("\n生成UserService接口:");
            interfaceFile.writeTo(System.out);
            
            System.out.println("\n生成UserServiceImpl类:");
            implFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            interfaceFile.writeTo(new File(path.toUri()));
            implFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成UserService.java和UserServiceImpl.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成用户实体类
     */
    public static void generateUserEntity() {
        // 创建字段
        FieldSpec idField = FieldSpec.builder(long.class, "id")
                .addModifiers(Modifier.PRIVATE)
                .build();
        
        FieldSpec nameField = FieldSpec.builder(String.class, "name")
                .addModifiers(Modifier.PRIVATE)
                .build();
        
        FieldSpec emailField = FieldSpec.builder(String.class, "email")
                .addModifiers(Modifier.PRIVATE)
                .build();
        
        // 创建构造函数
        MethodSpec constructor = MethodSpec.constructorBuilder()
                .addModifiers(Modifier.PUBLIC)
                .addParameter(long.class, "id")
                .addParameter(String.class, "name")
                .addParameter(String.class, "email")
                .addStatement("this.id = id")
                .addStatement("this.name = name")
                .addStatement("this.email = email")
                .build();
        
        // 创建getter和setter方法
        MethodSpec getIdMethod = MethodSpec.methodBuilder("getId")
                .addModifiers(Modifier.PUBLIC)
                .returns(long.class)
                .addStatement("return id")
                .build();
        
        MethodSpec setIdMethod = MethodSpec.methodBuilder("setId")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(long.class, "id")
                .addStatement("this.id = id")
                .build();
        
        MethodSpec getNameMethod = MethodSpec.methodBuilder("getName")
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return name")
                .build();
        
        MethodSpec setNameMethod = MethodSpec.methodBuilder("setName")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(String.class, "name")
                .addStatement("this.name = name")
                .build();
        
        MethodSpec getEmailMethod = MethodSpec.methodBuilder("getEmail")
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return email")
                .build();
        
        MethodSpec setEmailMethod = MethodSpec.methodBuilder("setEmail")
                .addModifiers(Modifier.PUBLIC)
                .returns(void.class)
                .addParameter(String.class, "email")
                .addStatement("this.email = email")
                .build();
        
        // 创建toString方法
        MethodSpec toStringMethod = MethodSpec.methodBuilder("toString")
                .addAnnotation(Override.class)
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return $S + id + $S + name + $S + email + $S", 
                        "User{id=", ", name='", "', email='", "'}")
                .build();
        
        // 创建类
        TypeSpec userClass = TypeSpec.classBuilder("User")
                .addModifiers(Modifier.PUBLIC)
                .addField(idField)
                .addField(nameField)
                .addField(emailField)
                .addMethod(constructor)
                .addMethod(getIdMethod)
                .addMethod(setIdMethod)
                .addMethod(getNameMethod)
                .addMethod(setNameMethod)
                .addMethod(getEmailMethod)
                .addMethod(setEmailMethod)
                .addMethod(toStringMethod)
                .build();
        
        // 创建Java文件
        JavaFile javaFile = JavaFile.builder("com.example.api.model", userClass)
                .build();

        try {
            // 输出到控制台
            System.out.println("\n生成User类:");
            javaFile.writeTo(System.out);
            
            // 输出到文件
            Path path = Paths.get("src/main/java");
            javaFile.writeTo(new File(path.toUri()));
            System.out.println("成功生成User.java文件");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}